package com.tiancheng.commom.pay.gaocheng;

import com.tiancheng.commom.pay.gaocheng.req.GcBasePayReq;
import com.tiancheng.commom.pay.gaocheng.req.merchant.*;
import com.tiancheng.commom.pay.gaocheng.req.pay.*;
import com.tiancheng.commom.pay.gaocheng.res.*;
import com.tiancheng.commom.pay.gaocheng.res.merchant.GcMerchantApplyBaseRes;
import com.tiancheng.commom.pay.gaocheng.res.merchant.GcMerchantApplyRes;
import com.tiancheng.trade.commom.core.exception.Asserts;
import com.tiancheng.trade.commom.core.utils.ForestHttpUtil;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;

import java.util.Map;
import java.util.Objects;

/**
 * 高成支付通道
 */
@Slf4j
public class GcPayChannel {

    public static final String GC = "高诚交易平台";

    private final GcPayProperties config;

    public GcPayChannel(GcPayProperties config) {
        this.config = config;
    }

    public GcPayProperties getConfig(){
        return this.config;
    }

    /**
     * 微信支付
     *
     * @param params
     * @return GcBaseResp<GcWxPayRes>
     */
    public GcBaseResp<GcWxPayRes> wechatPay(GcWxPayReq params) {
        this.setBaseParam(params);
        log.info(GC + "【微信支付下单】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() + "/oapi/s2/pay/c0/wxpay", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【微信支付下单】调用返回：{}", response);
        // 微信支付
        GcBaseResp<GcWxPayRes> wxPayResult = getGaoChengResponse(response, GcWxPayRes.class);
        Asserts.isTrue(wxPayResult.isOk(), StringUtils.isNotEmpty(wxPayResult.getMessage()) ? wxPayResult.getMessage() : GC + "【微信支付】调用失败！");
        log.info(GC + "【微信支付下单】返回:{}", JsonUtil.toJsonString(response));
        return wxPayResult;
    }

    /**
     * 支付宝支付
     *
     * @param params
     * @return GcBaseResp<GcWxPayRes>
     */
    public GcBaseResp<GcAliPayRes> aliPay(GcAliPayReq params) {
        this.setBaseParam(params);
        log.info(GC + "【支付宝支付下单】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() + "/oapi/s2/pay/c0/zfbpay", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【支付宝下单】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcAliPayRes> aliPayRes = getGaoChengResponse(response, GcAliPayRes.class);
        Asserts.isTrue(aliPayRes.isOk(), StringUtils.isNotEmpty(aliPayRes.getMessage()) ? aliPayRes.getMessage() : GC + "【支付宝下单】调用失败！");
        log.info(GC + "【支付宝下单】返回:{}", JsonUtil.toJsonString(response));
        return aliPayRes;
    }

    /**
     * 对公支付
     *
     * @param params
     * @return GcBaseResp<GcWxPayRes>
     */
    public GcBaseResp<GcCorppayRes> corpPay(GcCorppayReq params) {
        this.setBaseParam(params);
        log.info(GC + "【对公支付下单】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/s3/pay/c2/corppay", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【对公支付下单】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcCorppayRes> corpPayRes = getGaoChengResponse(response, GcCorppayRes.class);
        Asserts.isTrue(corpPayRes.isOk(), StringUtils.isNotEmpty(corpPayRes.getMessage()) ? corpPayRes.getMessage() : GC + "【对公支付下单】调用失败！");
        log.info(GC + "【对公支付下单】返回:{}", JsonUtil.toJsonString(response));
        return corpPayRes;
    }

    /**
     * 退款请求
     * @return
     */
    public GcBaseResp<GcOrderRefundRes> refund(GcRefundReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【退款】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/s2/pay/order/refund", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【退款】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcOrderRefundRes> refundRes = getGaoChengResponse(response, GcOrderRefundRes.class);
        Asserts.isTrue(refundRes.isOk(), StringUtils.isNotEmpty(refundRes.getMessage()) ? refundRes.getMessage() : GC + "【退款】调用失败！");
        log.info(GC + "【退款】返回:{}", JsonUtil.toJsonString(response));
        return refundRes;
    }

    /**
     * 查询退款
     * @return
     */
    public GcBaseResp<GcOrderRefundQueryRes> queryRefund(GcQueryRefundReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【查询退款】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/s2/pay/order/refund/status", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【查询退款】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcOrderRefundQueryRes> refundRes = getGaoChengResponse(response, GcOrderRefundQueryRes.class);
        Asserts.isTrue(refundRes.isOk(), StringUtils.isNotEmpty(refundRes.getMessage()) ? refundRes.getMessage() : GC + "【查询退款】调用失败！");
        log.info(GC + "【查询退款】返回:{}", JsonUtil.toJsonString(response));
        return refundRes;
    }

    /**
     * 查询支付订单
     * @return
     */
    public GcBaseResp<GcOrderQueryRes> queryPay(GcOrderQueryReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【订单查询】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/s2/pay/order/status", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【订单查询】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcOrderQueryRes> queryPayRes = getGaoChengResponse(response, GcOrderQueryRes.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【订单查询】调用失败！");
        log.info(GC + "【订单查询】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 查询支付订单
     * @return
     */
    public GcBaseResp<String> settle(GcSettleReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【订单对账预结算】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/s3/order/settle/exp", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【订单对账预结算】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<String> settlRes = getGaoChengResponse(response, String.class);
        Asserts.isTrue(settlRes.isOk(), StringUtils.isNotEmpty(settlRes.getMessage()) ? settlRes.getMessage() : GC + "【订单对账预结算】调用失败！");
        log.info(GC + "【订单对账预结算】返回:{}", JsonUtil.toJsonString(response));
        return settlRes;
    }

    /**
     * 商户主体注册
     * @param params
     * @return
     */
    public GcBaseResp<GcMerchantApplyBaseRes> apply(GcMerchantApplyBaseReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户主体注册】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m1/mch/c0m0/apply", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户主体注册】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcMerchantApplyBaseRes> queryPayRes = getGaoChengResponse(response, GcMerchantApplyBaseRes.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户主体注册】调用失败！");
        log.info(GC + "【商户注册申请】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 商户注册申请
     * @return
     */
    public GcBaseResp<GcMerchantApplyRes> merchantApply(GcMerchantApplyReq params){

        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户注册申请】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m2/mch/c2m2/apply", JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户注册申请】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcMerchantApplyRes> queryPayRes = getGaoChengResponse(response, GcMerchantApplyRes.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户注册申请】调用失败！");
        log.info(GC + "【商户注册申请】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 商户注册-附件上传
     * @return
     */
    public GcBaseResp<GcMerchantApplyRes> upload(GcMerchantUploadReq params){

        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户注册-附件上传】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m2/mch/c2m2/apply/upfile",
                JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户注册-附件上传】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcMerchantApplyRes> queryPayRes = getGaoChengResponse(response, GcMerchantApplyRes.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户注册-附件上传】调用失败！");
        log.info(GC + "【商户注册-附件上传】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 商户注册-附件确认
     * @return
     */
    public GcBaseResp<GcMerchantApplyRes> uploadConfirm(GcMerchantUploadConfirmReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户注册-附件上传-确认】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m2/mch/c2m2/apply/upfile/confirm",
                JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户注册-附件上传-确认】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<GcMerchantApplyRes> queryPayRes = getGaoChengResponse(response, GcMerchantApplyRes.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户注册-附件上传-确认】调用失败！");
        log.info(GC + "【商户注册-附件上传-确认】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 商户注册-发送短信验证码
     * @return
     */
    public GcBaseResp<String> smsSend(GcMerchantRegSmsSendReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户注册-发送短信验证码】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m2/mch/c2m2/apply/smsSend",
                JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户注册-发送短信验证码】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<String> queryPayRes = getGaoChengResponse(response, String.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户注册-发送短信验证码】调用失败！");
        log.info(GC + "【商户注册-发送短信验证码】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }

    /**
     * 商户注册-验证
     * @return
     */
    public GcBaseResp<String> smsVerify(GcMerchantRegVerifyReq params){
        GcSignUtils.doSign(params, this.config);
        log.info(GC + "【商户注册-短信验证】,params:{}", JsonUtil.toJsonString(params));
        final String response = ForestHttpUtil.getInstance().doPostForm(this.config.getHost() +  "/oapi/m2/mch/c2m2/apply/verify",
                JsonUtil.fromJson(JsonUtil.toJsonString(params), Map.class), null);
        log.info(GC + "【商户注册-短信验证】调用返回：{}", response);
        // 阿里支付
        GcBaseResp<String> queryPayRes = getGaoChengResponse(response, String.class);
        Asserts.isTrue(queryPayRes.isOk(), StringUtils.isNotEmpty(queryPayRes.getMessage()) ? queryPayRes.getMessage() : GC + "【商户注册-短信验证】调用失败！");
        log.info(GC + "【商户注册-短信验证】返回:{}", JsonUtil.toJsonString(response));
        return queryPayRes;
    }



    private void setBaseParam(GcBasePayReq params){
        params.setAccessId(this.config.getAccessId());
        params.setMchNo(this.config.getMchNo());
        params.setOrderType(this.config.getOrderType());
        //params.setSplitAcc(getSettleList(unifiedOrderBO.getSubSettles()));
        params.setNotifyUrl(this.config.getNotifyUrl());
        // 签名
        GcSignUtils.doSign(params, this.config);
    }

    /**
     * 高诚 接口返回结果转换
     *
     * @param resStr
     * @param bodyClass
     * @param <E>
     * @return
     */
    private <E> GcBaseResp<E> getGaoChengResponse(String resStr, Class<E> bodyClass) {
        if (StringUtils.isEmpty(resStr)) {
            return null;
        }
        Map<String, Object> map = JsonUtil.fromJson(resStr, Map.class);
        GcBaseResp<E> result = new GcBaseResp<>();
        result.setCode(MapUtils.getInteger(map, "code"));
        result.setMessage(MapUtils.getString(map, "message"));
        Object data = MapUtils.getObject(map, "data");
        if (Objects.nonNull(data)) {
            result.setData(JsonUtil.fromJson(JsonUtil.toJsonString(data), bodyClass));
        }
        return result;
    }
}
